#ifndef _PYOPENSG_WRAPPERS_H_
#define _PYOPENSG_WRAPPERS_H_

#include <boost/python.hpp>
#include <OpenSG/OSGMatrix.h>
#include <OpenSG/OSGVector.h>
#include <OpenSG/OSGQuaternion.h>
#include <OpenSG/OSGFieldContainerPtr.h>

namespace bp = boost::python;

/** Wrapper methods for getting values from some types. */
namespace osgwrap
{

bool osgInitWrapper(const unsigned int argc, bp::list pythonArgv);

OSG::Int32 ptrGetRefCount(OSG::FieldContainerPtr ptr);

OSG::UInt32 ptrGetFieldContainerId(OSG::FieldContainerPtr ptr);

bool isNullFC(OSG::FieldContainerPtr ptr);


template<typename T>
boost::python::tuple getValues2(T* obj)
{
   return boost::python::make_tuple((*obj)[0], (*obj)[1]);
}

template<typename T>
boost::python::tuple getValues3(T* obj)
{
   return boost::python::make_tuple((*obj)[0], (*obj)[1], (*obj)[2]);
}

template<typename T>
boost::python::tuple getValues4(T* obj)
{
   return boost::python::make_tuple((*obj)[0], (*obj)[1], (*obj)[2], (*obj)[3]);
}

/*
template<unsigned int SIZE, typename T>
boost::python::tuple getValues(T* obj)
{
   boost::python::tuple result(SIZE);

   for ( unsigned int i; i < SIZE; ++i )
   {
      tuple[i] = (*obj)[i];
   }

   return result;
}
*/

template boost::python::tuple getValues3(osg::Pnt3f*);
template boost::python::tuple getValues4(osg::Pnt4f*);

template boost::python::tuple getValues4(osg::Quaternion*);

template boost::python::tuple getValues3(osg::Vec3f*);
template boost::python::tuple getValues4(osg::Vec4f*);

template<typename T>
boost::python::tuple getValuesMatrix(osg::TransformationMatrix<T>* matrix)
{
   boost::python::tuple result(16);
   unsigned int count(0);

   for ( unsigned int i = 0; i < 4; ++i )
   {
      typename osg::TransformationMatrix<T>::VectorType& row = (*matrix)[i];

      for ( unsigned int j = 0; j < 4; ++j )
      {
         result[count++] = row[j];
      }
   }

   return result;
}

template boost::python::tuple getValuesMatrix(osg::Matrix*);
template boost::python::tuple getValuesMatrix(osg::Matrix4d*);

template<typename T, typename S>
void setArrayElement(T* obj, const unsigned int i, S value)
{
   (*obj)[i] = value;
}

template void setArrayElement(osg::Pnt3f*, const unsigned int, osg::Real32);
template void setArrayElement(osg::Pnt4f*, const unsigned int, osg::Real32);

template void setArrayElement(osg::Quaternion*, const unsigned int, osg::Real32);

template void setArrayElement(osg::Vec3f*, const unsigned int, osg::Real32);
template void setArrayElement(osg::Vec4f*, const unsigned int, osg::Real32);

inline boost::python::tuple getValueAsAxisDeg(osg::Quaternion* quat)
{
   boost::python::tuple result(4);
   osg::Real32 x, y, z, w;
   quat->getValueAsAxisDeg(x, y, z, w);
   result[0] = x;
   result[1] = y;
   result[2] = z;
   result[3] = w;
   return result;
}

inline osg::Real32 getValueAsAxisDeg(osg::Quaternion* quat,
                                     osg::Quaternion::VectorType* axis)
{
   osg::Real32 degrees;
   quat->getValueAsAxisDeg(*axis, degrees);
   return degrees;
}

inline boost::python::tuple getValueAsAxisRad(osg::Quaternion* quat)
{
   boost::python::tuple result(4);
   osg::Real32 x, y, z, w;
   quat->getValueAsAxisRad(x, y, z, w);
   result[0] = x;
   result[1] = y;
   result[2] = z;
   result[3] = w;
   return result;
}

inline osg::Real32 getValueAsAxisRad(osg::Quaternion* quat,
                                     osg::Quaternion::VectorType* axis)
{
   osg::Real32 radians;
   quat->getValueAsAxisRad(*axis, radians);
   return radians;
}

}

#endif /* _PYOPENSG_WRAPPERS_H_ */
